<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>着色器实现像素动画-小试牛刀-图片爆炸效果</title>
    <style>
        canvas{
            border: 1px solid #ccc;
        }
    </style>
</head>
<body>
    <canvas width="768" height="432"></canvas>

    <script src="/common/lib/gl-renderer.js"></script>
    <script type="module">
        /**
         * gl-renderer用法
         * 1.创建renderer对象
         * 2.创建webgl程序
         * 3.设置uniform变量
         * 4.设置缓冲区数据
         * 5.渲染
         * 
         * */ 

        //  1.
         const canvas = document.querySelector("canvas");
         const renderer = new GlRenderer(canvas);

        (async function(){
            // 2.
            const vertex = `
                attribute vec2 a_vertexPosition;
                attribute vec2 uv;
                varying vec2 vUv;
                
                void main() {
                    gl_PointSize = 1.0;
                    vUv = uv;
                    gl_Position = vec4(a_vertexPosition, 1, 1);
                }
            `;
            const fragment = `
                #ifdef GL_ES
                    precision mediump float;
                #endif
    
                varying vec2 vUv;
                uniform float uTime;
                uniform sampler2D tMap;

                float easing(float uTime){
                    return smoothstep(0.0, 0.4, uTime);
                }

                // 二维随机数
                float random(vec2 st){
                    return fract(sin(dot(st.xy, vec2(12.9898, 78.233))) * 43758.5453123);
                }
                // 二维噪声
                float noise(vec2 st){
                    vec2 i = floor(st);
                    vec2 f = fract(st);
                    f = smoothstep(0.0, 1.0, f);
                    // 对x、y方向分别做线性插值
                    return mix(
                        mix(random(i + vec2(0.0,0.0)), random(i + vec2(1.0,0.0)), f.x), 
                        mix(random(i + vec2(0.0,1.0)), random(i + vec2(1.0,1.0)), f.x), 
                        f.y);
                }
                
                void main() {
                    vec2 st = vUv;
                    // 生成随机向量进行位移
                    // float rx = mix(-0.2, 0.2, noise(random(st) + vec2(7881.32,0.0) + uTime));
                    // float ry = mix(-0.2, 0.2, noise(random(st) + vec2(0.0,1433.59) + uTime));

                    // 生成随机距离场
                    vec2 v = st - 0.5; // 运动的方向
                    v += normalize(v) * easing(uTime); // 运动的距离
                    float d = length(v);
                    float opacity = 1.0 - mix(0.0, 1.0, easing(uTime));
                    // d = 1.0 - step(uTime, d);

                    vec3 color = texture2D(tMap, vUv - v).rgb;

                    gl_FragColor.rgb = opacity * random(st) * color;
                    gl_FragColor.a = 1.0;
                }
            `;
            // https://blog.csdn.net/llimite/article/details/66974907
            const program = renderer.compileSync(fragment,vertex);
            renderer.useProgram(program);
    
            // 3.
            const texture = await renderer.loadTexture("./assets/girl3.jpg");
            renderer.uniforms.tMap = texture;
            renderer.uniforms.uTime = 0;
            // 4.
            const x = 1;
            const y = 1;
            renderer.setMeshData([{
                positions:[
                    [-x, -y],
                    [-x, y],
                    [x, y],
                    [x, -y],
                ],
                attributes:{
                    uv:[
                        [0, 0],
                        [0, 1],
                        [1, 1],
                        [1, 0],
                    ]
                },
                cells: [[0, 1, 2], [2, 0, 3]],
            }]);
    
            // 5.
            renderer.render();

            function update(t){
                renderer.uniforms.uTime = t * 0.00005;
                requestAnimationFrame(update);
            }
            update(0)

        })();

    </script>
</body>
</html>